/****************************************Copyright (c)****************************************************
 
**--------------File Info---------------------------------------------------------------------------------
** File name:                at32f415_wk_config.c
** Last modified Date:       2024.08.07
** Last Version:             Ver:1.0
** Descriptions:             
**                        
**--------------------------------------------------------------------------------------------------------
** Created by:               adm
** Created date:             2024.08.07
** Version:                  Ver:1.0
** Descriptions:             
**--------------------------------------------------------------------------------------------------------*/

/*
Copyright (c) [2024]     [BA6IV  ]   [SINEWAVE] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan
PSL v2.
You may obtain a copy of Mulan PSL v2 at:
         http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
  */
/* add user code end Header */

#include "at32f415_wk_config.h"

//按键状态标志位  0:无效   1：按键有效
__IO uint8_t		button1_SINGLE_Click_Flag;
__IO uint8_t		button1_DOUBLE_Click_Flag;
__IO uint8_t		button1_LONG_PRESS_Flag;
__IO uint8_t		button1_LONG_PRESS_HOLD_Flag;

__IO uint8_t		button2_SINGLE_Click_Flag;
__IO uint8_t		button2_DOUBLE_Click_Flag;
__IO uint8_t		button2_LONG_PRESS_Flag;
__IO uint8_t		button2_LONG_PRESS_HOLD_Flag;

__IO uint8_t		button3_SINGLE_Click_Flag;
__IO uint8_t		button3_DOUBLE_Click_Flag;
__IO uint8_t		button3_LONG_PRESS_Flag;
__IO uint8_t		button3_LONG_PRESS_HOLD_Flag;

struct Button button1;			//定义按钮结构体
struct Button button2;			//定义按钮结构体
struct Button button3;			//定义按钮结构体

void button1_SINGLE_Click_Handler(void* btn);						//单击动作函数
void button1_DOUBLE_Click_Handler(void* btn);						//双击动作函数
void button1_LONG_PRESS_START_Handler(void* btn);					//长按动作函数
void button1_LONG_PRESS_HOLD_Handler(void* btn);					//连击动作函数

void button2_SINGLE_Click_Handler(void* btn);						//单击动作函数
void button2_DOUBLE_Click_Handler(void* btn);						//双击动作函数
void button2_LONG_PRESS_START_Handler(void* btn);					//长按动作函数
void button2_LONG_PRESS_HOLD_Handler(void* btn);					//连击动作函数

void button3_SINGLE_Click_Handler(void* btn);						//单击动作函数
void button3_DOUBLE_Click_Handler(void* btn);						//双击动作函数
void button3_LONG_PRESS_START_Handler(void* btn);					//长按动作函数
void button3_LONG_PRESS_HOLD_Handler(void* btn);					//连击动作函数

/**
  * @brief  system clock config program（外部25MHz无源晶振）
  * @note   the system clock is configured as follow:
  *         system clock (sclk)   = hext * pll_mult
  *         system clock source   = HEXT_VALUE
  *         - hext                = HEXT_VALUE
  *         - sclk                = 150000000
  *         - ahbdiv              = 1
  *         - ahbclk              = 150000000
  *         - apb1div             = 2
  *         - apb1clk             = 75000000
  *         - apb2div             = 2
  *         - apb2clk             = 75000000
  *         - pll_mult            = 6
  *         - flash_wtcyc         = 4 cycle
  * @param  none
  * @retval none
  */
void wk_system_clock_config(void)
{
    /* reset crm */
    crm_reset();

    /* config flash psr register */
    flash_psr_set(FLASH_WAIT_CYCLE_4);

    /* enable lick */
    crm_clock_source_enable(CRM_CLOCK_SOURCE_LICK, TRUE);

    /* wait till lick is ready */
    while (crm_flag_get(CRM_LICK_STABLE_FLAG) != SET) {
    }

    /* enable hext */
    crm_clock_source_enable(CRM_CLOCK_SOURCE_HEXT, TRUE);

    /* wait till hext is ready */
    while (crm_hext_stable_wait() == ERROR) {
    }

    /* enable hick */
    crm_clock_source_enable(CRM_CLOCK_SOURCE_HICK, TRUE);

    /* wait till hick is ready */
    while (crm_flag_get(CRM_HICK_STABLE_FLAG) != SET) {
    }

    /* config pll clock resource */
    crm_pll_config(CRM_PLL_SOURCE_HEXT, CRM_PLL_MULT_6);

    /* enable pll */
    crm_clock_source_enable(CRM_CLOCK_SOURCE_PLL, TRUE);

    /* wait till pll is ready */
    while (crm_flag_get(CRM_PLL_STABLE_FLAG) != SET) {
    }

    /* config ahbclk */
    crm_ahb_div_set(CRM_AHB_DIV_1);

    /* config apb2clk, the maximum frequency of APB2 clock is 75 MHz  */
    crm_apb2_div_set(CRM_APB2_DIV_2);

    /* config apb1clk, the maximum frequency of APB1 clock is 75 MHz  */
    crm_apb1_div_set(CRM_APB1_DIV_2);

    /* enable auto step mode */
    crm_auto_step_mode_enable(TRUE);

    /* select pll as system clock source */
    crm_sysclk_switch(CRM_SCLK_PLL);

    /* wait till pll is used as system clock source */
    while (crm_sysclk_switch_status_get() != CRM_SCLK_PLL) {
    }

    /* disable auto step mode */
    crm_auto_step_mode_enable(FALSE);

    /* update system_core_clock global variable */
    system_core_clock_update();
}

/**
  * @brief  config systick and enable interrupt.
  * @param  none
  * @retval none
  */
uint32_t systick_interrupt_config(uint32_t ticks)
{
    if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) {
        return (1UL);
    }

    SysTick->LOAD  = (uint32_t)(ticks - 1UL);
    SysTick->VAL   = 0UL;
    SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk |
                     SysTick_CTRL_ENABLE_Msk;
    return (0UL);
}

/**
  * @brief  片内外设时钟配置函数
  * @param  none
  * @retval none
  */
void wk_periph_clock_config(void)
{
    /* enable dma1 periph clock */
    crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);

    /* enable iomux periph clock */
    crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);

    /* enable gpioa periph clock */
    crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);

    /* enable gpiob periph clock */
    crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);

    /* enable gpiod periph clock */
    crm_periph_clock_enable(CRM_GPIOD_PERIPH_CLOCK, TRUE);

    /* enable tmr1 periph clock */
    crm_periph_clock_enable(CRM_TMR1_PERIPH_CLOCK, TRUE);

    /* enable i2c1 periph clock */
    crm_periph_clock_enable(CRM_I2C1_PERIPH_CLOCK, TRUE);
}

/**
  * @brief  Debug编程IO初始化配置函数（SWD模式）
  * @param  none
  * @retval none
  */
void wk_debug_config(void)
{
    /* jtag-dp disabled and sw-dp enabled */
    gpio_pin_remap_config(SWJTAG_GMUX_010, TRUE);
}

/**
  * @brief  中端配置函数
  * @param  none
  * @retval none
  */
void wk_nvic_config(void)
{
    //使用优先级分组4
    nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
    
    //配置Systick中断优先级
//    nvic_irq_enable(SysTick_IRQn, 0, 0);
    
    //TMR11 1ms中断
    nvic_irq_enable(TMR1_TRG_HALL_TMR11_IRQn, 0, 0);
}


/**
  * @brief  I2C1初始化配置函数
  * @param  none
  * @retval none
  */
void wk_i2c1_init(void)
{
    gpio_init_type gpio_init_struct;

    gpio_default_para_init(&gpio_init_struct);

    /* configure the SCL pin */
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_init_struct.gpio_pins = GPIO_PINS_6;
    gpio_init(GPIOB, &gpio_init_struct);

    /* configure the SDA pin */
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_init_struct.gpio_pins = GPIO_PINS_7;
    gpio_init(GPIOB, &gpio_init_struct);

    i2c_init(I2C1, I2C_FSMODE_DUTY_2_1, 400000);
    i2c_own_address1_set(I2C1, I2C_ADDRESS_MODE_7BIT, 0x0);
    i2c_ack_enable(I2C1, TRUE);
    i2c_clock_stretch_enable(I2C1, TRUE);
    i2c_general_call_enable(I2C1, FALSE);

//    i2c_dma_enable(I2C1, TRUE);

    i2c_enable(I2C1, TRUE);

}

/**
  * @brief  TMR1定时器初始化配置函数
  * @param  none
  * @retval none
  */
void wk_tmr1_init(void)
{
    gpio_init_type gpio_init_struct;
    tmr_output_config_type tmr_output_struct;
    tmr_brkdt_config_type tmr_brkdt_struct;

    gpio_default_para_init(&gpio_init_struct);

    /* configure the CH1 pin */
    gpio_init_struct.gpio_pins = GPIO_PINS_8;
    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_init(GPIOA, &gpio_init_struct);

    /* configure counter settings */
    tmr_base_init(TMR1, 585973/MyKey.tone, 0);
    tmr_cnt_dir_set(TMR1, TMR_COUNT_UP);
    tmr_clock_source_div_set(TMR1, TMR_CLOCK_DIV1);
    tmr_repetition_counter_set(TMR1, 0);
    tmr_period_buffer_enable(TMR1, TRUE);

    /* configure primary mode settings */
    tmr_sub_sync_mode_set(TMR1, FALSE);
    tmr_primary_mode_select(TMR1, TMR_PRIMARY_SEL_RESET);

    /* configure channel 1 output settings */
    tmr_output_struct.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_A;
    tmr_output_struct.oc_output_state = TRUE;
    tmr_output_struct.occ_output_state = FALSE;
    tmr_output_struct.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH;
    tmr_output_struct.occ_polarity = TMR_OUTPUT_ACTIVE_HIGH;
    tmr_output_struct.oc_idle_state = FALSE;
    tmr_output_struct.occ_idle_state = FALSE;
    tmr_output_channel_config(TMR1, TMR_SELECT_CHANNEL_1, &tmr_output_struct);
    tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_1, 0);
    tmr_output_channel_buffer_enable(TMR1, TMR_SELECT_CHANNEL_1, FALSE);

    tmr_output_channel_immediately_set(TMR1, TMR_SELECT_CHANNEL_1, FALSE);

    /* configure break and dead-time settings */
    tmr_brkdt_struct.brk_enable = FALSE;
    tmr_brkdt_struct.auto_output_enable = FALSE;
    tmr_brkdt_struct.brk_polarity = TMR_BRK_INPUT_ACTIVE_LOW;
    tmr_brkdt_struct.fcsoen_state = FALSE;
    tmr_brkdt_struct.fcsodis_state = FALSE;
    tmr_brkdt_struct.wp_level = TMR_WP_OFF;
    tmr_brkdt_struct.deadtime = 0;
    tmr_brkdt_config(TMR1, &tmr_brkdt_struct);


    /* configure dma overflow */
    tmr_dma_request_enable(TMR1, TMR_OVERFLOW_DMA_REQUEST, TRUE);
    tmr_output_enable(TMR1, TRUE);

//    tmr_counter_enable(TMR1, TRUE);
}


/**
  * @brief  TMR11定时器初始化配置函数
  * @param  none
  * @retval none
  */
void wk_tmr11_init(void)
{
    /* enable tmr11 periph clock */
    crm_periph_clock_enable(CRM_TMR11_PERIPH_CLOCK, TRUE);
    
    /* configure counter settings */
    tmr_base_init(TMR11, 999, 149);
    tmr_cnt_dir_set(TMR11, TMR_COUNT_UP);
    tmr_clock_source_div_set(TMR11, TMR_CLOCK_DIV1);
    tmr_period_buffer_enable(TMR11, FALSE);
    
    /* overflow interrupt enable */
    tmr_interrupt_enable(TMR11, TMR_OVF_INT, TRUE);

    tmr_counter_enable(TMR11, TRUE);
}

/**
  * @brief  tmr1触发DMA初始化配置函数
  * @param  none
  * @retval none
  */
void wk_dma1_channel1_init(void)
{
    dma_init_type dma_init_struct;

    dma_reset(DMA1_CHANNEL1);
    dma_default_para_init(&dma_init_struct);
    dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;
    dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
    dma_init_struct.memory_inc_enable = TRUE;
    dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
    dma_init_struct.peripheral_inc_enable = FALSE;
    dma_init_struct.priority = DMA_PRIORITY_HIGH;
    dma_init_struct.loop_mode_enable = TRUE;
    dma_init(DMA1_CHANNEL1, &dma_init_struct);

    /* flexible function enable */
    dma_flexible_config(DMA1, FLEX_CHANNEL1, DMA_FLEXIBLE_TMR1_OVERFLOW);

}

/**
  * @brief  i2c1_rx DMA初始化配置函数
  * @param  none
  * @retval none
  */
void wk_dma1_channel2_init(void)
{
    dma_init_type dma_init_struct;

    dma_reset(DMA1_CHANNEL2);
    dma_default_para_init(&dma_init_struct);
    dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
    dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
    dma_init_struct.memory_inc_enable = TRUE;
    dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
    dma_init_struct.peripheral_inc_enable = FALSE;
    dma_init_struct.priority = DMA_PRIORITY_MEDIUM;
    dma_init_struct.loop_mode_enable = FALSE;
    dma_init(DMA1_CHANNEL2, &dma_init_struct);

    /* flexible function enable */
    dma_flexible_config(DMA1, FLEX_CHANNEL2, DMA_FLEXIBLE_I2C1_RX);

}

/**
  * @brief  i2c1_tx 初始化配置函数
  * @param  none
  * @retval none
  */
void wk_dma1_channel3_init(void)
{
    dma_init_type dma_init_struct;

    dma_reset(DMA1_CHANNEL3);
    dma_default_para_init(&dma_init_struct);
    dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;
    dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
    dma_init_struct.memory_inc_enable = TRUE;
    dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
    dma_init_struct.peripheral_inc_enable = FALSE;
    dma_init_struct.priority = DMA_PRIORITY_MEDIUM;
    dma_init_struct.loop_mode_enable = FALSE;
    dma_init(DMA1_CHANNEL3, &dma_init_struct);

    /* flexible function enable */
    dma_flexible_config(DMA1, FLEX_CHANNEL3, DMA_FLEXIBLE_I2C1_TX);

}

/**
  * @brief  DMA通道参数配置函数
  * @param  none
  * @retval none
  */
void wk_dma_channel_config(dma_channel_type *dmax_channely, uint32_t peripheral_base_addr, uint32_t memory_base_addr, uint16_t buffer_size)
{
    dmax_channely->dtcnt = buffer_size;
    dmax_channely->paddr = peripheral_base_addr;
    dmax_channely->maddr = memory_base_addr;

}


/**
* @brief  实体按钮电平读取函数
* @param  none
* @retval 返回按钮引脚电平值
*/
uint8_t Read_button1(void) {   return Read_Button1();  }
uint8_t Read_button2(void) {   return Read_Button2();  }
uint8_t Read_button3(void) {   return Read_Button3();  }

/**
  * @brief  用户按键初始化配置函数
  * @param  none
  * @retval none
  */
void user_button_init(void)
{
	//按钮IO初始化
    gpio_init_type gpio_init_struct;
    gpio_default_para_init(&gpio_init_struct);

    /* 电键、按钮输入端口初始化 */
    gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
    gpio_init_struct.gpio_pins = Button1_PIN | Button2_PIN | Button3_PIN;
    gpio_init_struct.gpio_pull = GPIO_PULL_UP;
    gpio_init(GPIOA, &gpio_init_struct);
    
    //初始化按钮对象
	button_init(&button1, Read_button1, 0);		//高电平有效
    button_init(&button2, Read_button2, 0);		//高电平有效
    button_init(&button3, Read_button3, 0);		//高电平有效

	//为按钮绑定动作函数，这里使用单击和长按动作
	button_attach(&button1, SINGLE_CLICK, 		(BtnCallback)button1_SINGLE_Click_Handler);			//单击
	button_attach(&button1, DOUBLE_CLICK, 		(BtnCallback)button1_DOUBLE_Click_Handler);			//双击
	button_attach(&button1, LONG_PRESS_START,	(BtnCallback)button1_LONG_PRESS_START_Handler);	    //长按
	button_attach(&button1, LONG_PRESS_HOLD,	(BtnCallback)button1_LONG_PRESS_HOLD_Handler);		//连击
    
    //为按钮绑定动作函数，这里使用单击和长按动作
	button_attach(&button2, SINGLE_CLICK, 		(BtnCallback)button2_SINGLE_Click_Handler);			//单击
	button_attach(&button2, DOUBLE_CLICK, 		(BtnCallback)button2_DOUBLE_Click_Handler);			//双击
	button_attach(&button2, LONG_PRESS_START,	(BtnCallback)button2_LONG_PRESS_START_Handler);	    //长按
	button_attach(&button2, LONG_PRESS_HOLD,	(BtnCallback)button2_LONG_PRESS_HOLD_Handler);		//连击
    
    //为按钮绑定动作函数，这里使用单击和长按动作
	button_attach(&button3, SINGLE_CLICK, 		(BtnCallback)button3_SINGLE_Click_Handler);			//单击
	button_attach(&button3, DOUBLE_CLICK, 		(BtnCallback)button3_DOUBLE_Click_Handler);			//双击
	button_attach(&button3, LONG_PRESS_START,	(BtnCallback)button3_LONG_PRESS_START_Handler);	    //长按
	button_attach(&button3, LONG_PRESS_HOLD,	(BtnCallback)button3_LONG_PRESS_HOLD_Handler);		//连击
	
	//启动按钮对象
	button_start(&button1);
    button_start(&button2);
    button_start(&button3);
}

/* 按钮动作函数 */
//按钮单击回调函数
void button1_SINGLE_Click_Handler(void* btn)
{
	button1_SINGLE_Click_Flag = 1;
}

//按钮双击回调函数
void button1_DOUBLE_Click_Handler(void* btn)
{
	button1_DOUBLE_Click_Flag = 1;
}

//按钮长按回调函数
void button1_LONG_PRESS_START_Handler(void* btn)
{
	button1_LONG_PRESS_Flag = 1;
}

//按钮连击回调函数
void button1_LONG_PRESS_HOLD_Handler(void* btn)
{
	button1_LONG_PRESS_HOLD_Flag = 1;
}

/* 按钮动作函数 */
//按钮单击回调函数
void button2_SINGLE_Click_Handler(void* btn)
{
	button2_SINGLE_Click_Flag = 1;
}

//按钮双击回调函数
void button2_DOUBLE_Click_Handler(void* btn)
{
	button2_DOUBLE_Click_Flag = 1;
}

//按钮长按回调函数
void button2_LONG_PRESS_START_Handler(void* btn)
{
	button2_LONG_PRESS_Flag = 1;
}

//按钮连击回调函数
void button2_LONG_PRESS_HOLD_Handler(void* btn)
{
	button2_LONG_PRESS_HOLD_Flag = 1;
}

/* 按钮动作函数 */
//按钮单击回调函数
void button3_SINGLE_Click_Handler(void* btn)
{
	button3_SINGLE_Click_Flag = 1;
}

//按钮双击回调函数
void button3_DOUBLE_Click_Handler(void* btn)
{
	button3_DOUBLE_Click_Flag = 1;
}

//按钮长按回调函数
void button3_LONG_PRESS_START_Handler(void* btn)
{
	button3_LONG_PRESS_Flag = 1;
}

//按钮连击回调函数
void button3_LONG_PRESS_HOLD_Handler(void* btn)
{
	button3_LONG_PRESS_HOLD_Flag = 1;
}

